﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Http;
using System.Configuration;
using System.IO;
using System.Net;
using Newtonsoft.Json.Linq;
using System.Data;

namespace DataCollectionSystem
{


	class ApiService
	{
		public static readonly string BaseUri = ConfigurationManager.AppSettings["ApiUri"];
		//public static readonly string BaseUri = "https://api.sszlbg.cn";
		/// <summary>
		/// 获取用户名
		/// </summary>
		/// <returns></returns>
		private static string GetUser()
		{
			if (ConfigurationManager.AppSettings["user"] != null && ConfigurationManager.AppSettings["user"] != "" &&
				ConfigurationManager.AppSettings["Token"] != null && ConfigurationManager.AppSettings["Token"] != "" &&
				ConfigurationManager.AppSettings["exp"] != null && ConfigurationManager.AppSettings["exp"] != ""
				)
			{
				return ConfigurationManager.AppSettings["user"];
			}
			else
				throw new Exception("配置文件错误");

		}
		/// <summary>
		/// 获取Token
		/// </summary>
		/// <returns></returns>
		private static string GetToken()
		{
			if (ConfigurationManager.AppSettings["user"] != null && ConfigurationManager.AppSettings["user"] != "" &&
				ConfigurationManager.AppSettings["Token"] != null && ConfigurationManager.AppSettings["Token"] != "" &&
				ConfigurationManager.AppSettings["exp"] != null && ConfigurationManager.AppSettings["exp"] != ""
				)
			{
				return ConfigurationManager.AppSettings["Token"];
			}
			else
				throw new Exception("配置文件错误");

		}
		public static List<Dictionary<string, string>> GetSensorData(string device_id,string type_name = null)
		{
			if (isLogin())
			{
				try
				{
					System.Net.HttpStatusCode StatusCode;

					
					List<KeyValuePair<string, string>> Heads = new List<KeyValuePair<string, string>>();
					Heads.Add(new KeyValuePair<string, string>("Authorization", "Bearer " + GetToken()));

					string rec;
					if (type_name != null)
					{
						List<KeyValuePair<string, string>> arg = new List<KeyValuePair<string, string>>();
						arg.Add(new KeyValuePair<string, string>("type_name", type_name));
						rec = ApiService.GetResponseByGet("v1/Data/" + device_id, arg, out StatusCode, Heads);
					}
					else
						rec = ApiService.GetResponseByGet("v1/Data/" + device_id, null, out StatusCode, Heads);

					if (StatusCode == HttpStatusCode.OK)
					{
						
						JObject jObject = JObject.Parse(rec);
						if (jObject.Property("count") != null && jObject.Property("deviceId") != null)
						{

							int count = 0;
							try
							{
								count = int.Parse(jObject["count"].ToString());
							}
							catch
							{
								throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
							}

							if (count > 0)
							{

								JArray SensorTypes = JArray.Parse(jObject["Data"].ToString(Newtonsoft.Json.Formatting.None, null));


								List<Dictionary<string, string>> types = new List<Dictionary<string, string>>();


								for (int i = 0; i < count; i++)
								{
									Dictionary<string, string> dictionary = new Dictionary<string, string>();
									JObject type = JObject.Parse(SensorTypes[i].ToString());

									dictionary.Add("data", type["data"].ToString());
									dictionary.Add("date", type["date"].ToString());
									dictionary.Add("describe", type["describe"].ToString());
									dictionary.Add("unit", type["unit"].ToString());
									types.Add(dictionary);
								}
								return types;

							}
							else
							{
								return null;
							}


						}

						throw new Exception($"请求回复错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.InternalServerError)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"服务器错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"服务器错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.BadRequest)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"登录信息错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"登录信息错误:{rec}");
					}
					else
					{
						throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
					}


				}
				catch (Exception ex)
				{
					throw new Exception($"错误:\r\n{ex.Message}");
				}
			}
			else
				throw new Exception("登录信息过期,请重新登录");
		}
		/// <summary>
		/// 获取设备传感器类型
		/// </summary>
		/// <param name="device_id"></param>
		/// <returns></returns>
		public static List<Dictionary<string, string>> GetSensorType(string device_id)
		{
			if (isLogin())
			{
				try
				{
					System.Net.HttpStatusCode StatusCode;
					List<KeyValuePair<string, string>> Heads = new List<KeyValuePair<string, string>>();
					Heads.Add(new KeyValuePair<string, string>("Authorization", "Bearer " + GetToken()));
					string rec = ApiService.GetResponseByGet("v1/Device/SensorType/" + device_id, null, out StatusCode, Heads);
					if (StatusCode == HttpStatusCode.OK)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Property("SensorTypes") != null && jObject.Property("deviceId") != null)
						{
							 
							JArray SensorTypes = JArray.Parse(jObject["SensorTypes"].ToString(Newtonsoft.Json.Formatting.None, null));
							int count = SensorTypes.Count;
							if (count > 0)
							{
								List<Dictionary<string, string>> types = new List<Dictionary<string, string>>();
								

								for (int i = 0; i < count; i++)
								{
									Dictionary<string, string> dictionary = new Dictionary<string, string>();
									JObject type = JObject.Parse(SensorTypes[i].ToString());
									dictionary.Add("type_name", type["type_name"].ToString());
									dictionary.Add("Name", type["Name"].ToString());
									dictionary.Add("unit", type["unit"].ToString());
									types.Add(dictionary);
								}
								return types;

							}
							else
							{
								return null;
							}


						}

						throw new Exception($"请求回复错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.InternalServerError)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"服务器错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"服务器错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.BadRequest)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"登录信息错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"登录信息错误:{rec}");
					}
					else
					{
						throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
					}


				}
				catch (Exception ex)
				{
					throw new Exception($"错误:\r\n{ex.Message}");
				}
			}
			else
				throw new Exception("登录信息过期,请重新登录");
		}
		/// <summary>
		/// 获取设备列表
		/// </summary>
		/// <returns></returns>
		public static DataTable GetDevices()
		{
			if (isLogin())
			{
				try
				{
					System.Net.HttpStatusCode StatusCode;
					List<KeyValuePair<string, string>> Heads = new List<KeyValuePair<string, string>>();
					Heads.Add(new KeyValuePair<string, string>("Authorization", "Bearer " + GetToken()));
					string rec = ApiService.GetResponseByGet("v1/Device", null, out StatusCode, Heads);
					if (StatusCode == HttpStatusCode.OK)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Property("user") != null && jObject.Property("count") != null)
						{
							int count = 0;
							try
							{
								count = int.Parse(jObject["count"].ToString());
							}
							catch
							{
								throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
							}
							if (count > 0)
							{
								DataTable devices_table = new DataTable();
								devices_table.Columns.Add("deviceId", typeof(string)); //数据类型为 文本
								devices_table.Columns.Add("model", typeof(string)); //数据类型为 文本
								devices_table.Columns.Add("imei", typeof(string)); //数据类型为 文本
								devices_table.Columns.Add("time", typeof(string)); //数据类型为 文本
								
								for (int i = 0; i < count; i++)
								{
									DataRow device = devices_table.NewRow();
									device["deviceId"] = ( jObject["devices"][i]["deviceId"].ToString());
									device["model"] = (jObject["devices"][i]["model"].ToString());
									device["imei"] = ( jObject["devices"][i]["imei"].ToString());
									device["time"] = ( jObject["devices"][i]["time"].ToString());
									devices_table.Rows.Add(device);
								}
								return devices_table;

							}
							else
							{
								return null;
							}

						}

						throw new Exception($"请求回复错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.InternalServerError)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"服务器错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"服务器错误:{rec}");
					}
					else if (StatusCode == HttpStatusCode.BadRequest)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
							throw new Exception($"登录信息错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
						else
							throw new Exception($"登录信息错误:{rec}");
					}
					else
					{
						throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
					}


				}
				catch (Exception ex)
				{
					throw new Exception($"错误:\r\n{ex.Message}");
				}
			}
			else
				throw new Exception("登录信息过期,请重新登录");
	}
	

		/// <summary>
		/// 用户是否登录
		/// </summary>
		/// <returns></returns>
		public static bool isLogin()
		{
			if (ConfigurationManager.AppSettings["user"] != null && ConfigurationManager.AppSettings["user"] != "" &&
				ConfigurationManager.AppSettings["Token"] != null && ConfigurationManager.AppSettings["Token"] != "" &&
				ConfigurationManager.AppSettings["exp"] != null && ConfigurationManager.AppSettings["exp"] != ""
				)
			{
				DateTime exp = DateTime.ParseExact(ConfigurationManager.AppSettings["exp"], "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
				DateTime now = DateTime.Now;
				if (exp.CompareTo( now) >= 0)
				{
					return true;
				}
				else
					return false;

			}
			else
				return false;
		}

		/// <summary>
		/// 用户登录
		/// </summary>
		/// <param name="user"></param>
		/// <param name="pwd"></param>
		/// <returns></returns>
		public static bool Login(string user,string pwd)
		{
			System.Net.HttpStatusCode StatusCode;
			JObject userObject = new JObject();
			userObject.Add("user", user);
			userObject.Add("pwd", pwd);

			try
			{
				string rec = ApiService.HttpPostJsonRequestAsync("v1/login", userObject,out StatusCode);
				if (StatusCode == HttpStatusCode.OK)
				{
					JObject jObject = JObject.Parse(rec);
					if (jObject.Property("user") != null && jObject.Property("Token") != null)
					{
						//获取Token
						string Token = jObject["Token"].ToString();
						string[] strArr = Token.Split('.');
						//验证是否有3个断
						if (strArr.Length == 3)
						{
							//解密并转换Json对象 获取过期时间
							JObject jObjectJwt = JObject.Parse(JwtBase64UrlEncode(strArr[1]));
							//写配置
							Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
							
							config.AppSettings.Settings["user"].Value = jObject["user"].ToString();//设置登录用户名
							config.AppSettings.Settings["Token"].Value = Token;//设置Tokken
							config.AppSettings.Settings["exp"].Value = GetDateTimeFrom1970Ticks(jObjectJwt["exp"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");//设置过期时间

							// Save the configuration file.
							config.AppSettings.SectionInformation.ForceSave = true;
							config.Save(ConfigurationSaveMode.Modified);
							// Force a reload of the changed section.
							ConfigurationManager.RefreshSection("appSettings");

							return true;
						}

					}

					throw new Exception($"请求回复错误:{rec}");
				}
				else if (StatusCode == HttpStatusCode.InternalServerError)
				{
					JObject jObject = JObject.Parse(rec);
					if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
						throw new Exception($"服务器错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
					else
						throw new Exception($"服务器错误:{rec}");
				}
				else if (StatusCode == HttpStatusCode.BadRequest)
				{
					JObject jObject = JObject.Parse(rec);
					if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
						throw new Exception($"登录失败:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
					else
						throw new Exception($"登录失败:{rec}");
				}
				else
				{
					throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
				}
			}
			catch (Exception ex)
			{
				throw new Exception($"错误:\r\n{ex.Message}");
			}
		}

		/// <summary>
		/// 用户退出登录
		/// </summary>
		/// <returns></returns>
		public static void Logout()
		{
			System.Net.HttpStatusCode StatusCode;


			try
			{
				if (isLogin())
				{

					string Token = GetToken();


					//写配置
					Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

					config.AppSettings.Settings["user"].Value = "";//设置登录用户名
					config.AppSettings.Settings["Token"].Value = "";//设置Tokken
					config.AppSettings.Settings["exp"].Value = "";//设置过期时间

					// Save the configuration file.
					config.AppSettings.SectionInformation.ForceSave = true;
					config.Save(ConfigurationSaveMode.Modified);
					// Force a reload of the changed section.
					ConfigurationManager.RefreshSection("appSettings");

					List<KeyValuePair<string, string>> Heads = new List<KeyValuePair<string, string>>();
					Heads.Add(new KeyValuePair<string, string>("Authorization", "Bearer " + Token));
					string rec = ApiService.GetResponseByGet("v1/logout", null, out StatusCode, Heads);





					if (StatusCode == HttpStatusCode.OK)
					{
						JObject jObject = JObject.Parse(rec);
						if (jObject.Property("user") != null && jObject.Property("logout_date") != null)
						{
							return;
						}
						//throw new Exception($"请求回复错误:{rec}");
					}
					//else if (StatusCode == HttpStatusCode.InternalServerError)
					//{
					//	JObject jObject = JObject.Parse(rec);
					//	if (jObject.Count > 0 && jObject.Property("errorMsg") != null && jObject.Property("error") != null)
					//		throw new Exception($"服务器错误:\r\n{jObject["errorMsg"]}:{jObject["error"]}");
					//	else
					//		throw new Exception($"服务器错误:{rec}");
					//}
					//else
						//throw new Exception($"请求出错:状态码:{StatusCode}内容:{rec}");
					
				}
				//else
				//{
				//	throw new Exception($"没有登录");
				//}

			}
			catch (Exception ex)
			{
				ex.ToString();
				//throw new Exception($"错误:\r\n{ex.Message}");
			}
		}
		/// <summary>
		/// Jwt解密Base64
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		private static string JwtBase64UrlEncode(string input)
		{
			int addlen;
			int remainder = (input.Length) % 4;
			if (remainder != 0)
			{
				addlen = 4 - remainder;
				for (int i = 0; i < addlen; i++)
					input += "=";
			}
			input = input.Replace("-_", "+/");
			byte[] inArray = Convert.FromBase64String(input);

			return System.Text.Encoding.UTF8.GetString(inArray); ;
		}
		/// <summary>
		/// 时间戳转DateTime
		/// </summary>
		/// <param name="timeStamp"></param>
		/// <returns></returns>
		private static DateTime GetDateTimeFrom1970Ticks(string timeStamp)
		{
			DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));

			return dtStart.AddSeconds(long.Parse(timeStamp));
		}

		private static readonly HttpClient HttpClient;

		public static string User1 { get => User; set => User = value; }
		public static string User { get; set; }

		static ApiService()
		{
			var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };
			HttpClient = new HttpClient(handler);
			HttpClient.BaseAddress = new Uri(BaseUri);
		}


		/// <summary>
		/// get请求，可以对请求头进行多项设置
		/// </summary>
		/// <param name="url"></param>
		/// <param name="paramArray"></param>
		/// <returns></returns>
		public static string GetResponseByGet( string url, List<KeyValuePair<string, string>> paramArray, out System.Net.HttpStatusCode StatusCode, List<KeyValuePair<string, string>> HttpHadres = null)
		{
			string result = "";

			var httpclient = ApiService.HttpClient;

			url = url + "?" + BuildParam(paramArray);
			httpclient.DefaultRequestHeaders.Clear();
			if (HttpHadres != null)
			{
				foreach (var item in HttpHadres)
					httpclient.DefaultRequestHeaders.Add(item.Key, item.Value);
			}

			var response = httpclient.GetAsync(url).Result;
			if (response.IsSuccessStatusCode)
			{
				Stream myResponseStream = response.Content.ReadAsStreamAsync().Result;
				StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
				result = myStreamReader.ReadToEnd();
				myStreamReader.Close();
				myResponseStream.Close();
				StatusCode = response.StatusCode;
				return result;
			}
			throw new Exception($"{response.StatusCode}:\r\n{response.Content.ReadAsStringAsync().Result}");

		}
		public static string HttpPostJsonRequestAsync(string Url, JObject paramArray, out System.Net.HttpStatusCode StatusCode)
		{
			string result = "";
			var postData = paramArray.ToString(Newtonsoft.Json.Formatting.None, null);

			var data = Encoding.UTF8.GetBytes(postData);

			try
			{
				using (HttpClient http = new HttpClient())
				{
					http.BaseAddress = new Uri(BaseUri);

					HttpResponseMessage message = null;
					using (Stream dataStream = new MemoryStream(data ?? new byte[0]))
					{
						using (HttpContent content = new StreamContent(dataStream))
						{
							content.Headers.Add("Content-Type", "application/json");
							var task = http.PostAsync(Url, content);
							message = task.Result;
						}
					}
					if (message != null)
					{
						using (message)
						{
							StatusCode = message.StatusCode;
							result = message.Content.ReadAsStringAsync().Result;
							return result;
						}

					}
					else
					{
						throw new Exception($"message:为空");
					}

				}
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message);
			}

		}
		public static string HttpPostRequestAsync(string Url, List<KeyValuePair<string, string>> paramArray, out System.Net.HttpStatusCode StatusCode ,string ContentType = "application/x-www-form-urlencoded")
		{
			string result = "";
			var postData = BuildParam(paramArray);

			var data = Encoding.UTF8.GetBytes(postData);
			
			try
			{
				using (HttpClient http = new HttpClient())
				{
					http.BaseAddress = new Uri(BaseUri);

					HttpResponseMessage message = null;
					using (Stream dataStream = new MemoryStream(data ?? new byte[0]))
					{
						using (HttpContent content = new StreamContent(dataStream))
						{

							content.Headers.Add("Content-Type", ContentType);
							var task = http.PostAsync(Url, content);
							message = task.Result;
						}
					}
					if (message != null)
					{
						using (message)
						{
							StatusCode = message.StatusCode;
							result = message.Content.ReadAsStringAsync().Result;
							return result;
						}

					}
					else
					{
						throw new Exception($"message:为空");
					}
				}
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message);
			}
			
		}

		private static string Encode(string content, Encoding encode = null)
		{
			if (encode == null) return content;

			return System.Web.HttpUtility.UrlEncode(content, Encoding.UTF8);

		}

		private static string BuildParam(List<KeyValuePair<string, string>> paramArray, Encoding encode = null)
		{
			string url = "";

			if (encode == null) encode = Encoding.UTF8;

			if (paramArray != null && paramArray.Count > 0)
			{
				var parms = "";
				foreach (var item in paramArray)
				{
					parms += string.Format("{0}={1}&", Encode(item.Key, encode), Encode(item.Value, encode));
				}
				if (parms != "")
				{
					parms = parms.TrimEnd('&');
				}
				url += parms;

			}
			return url;
		}

	}
}
